package main

//go get github.com/yuin/gopher-lua
import (
	"MqttCloudProtocolServer/publiclib/define"
	"MqttCloudProtocolServer/publiclib/logiclib"
	"flag"
	"fmt"
	"log"
	"os"
	"os/signal"
	"path/filepath"
	"strings"
	"sync"
	"syscall"
	"time"

	"github.com/chai2010/winsvc"
	"github.com/wonderivan/logger"
)

//服务名称：MQTT2TCPMain
//显示名称：MQTT2TCP主启动进程与守护进程
//描述：守护内部进程运转。少干活，多稳定
var (
	appPath              string
	flagServiceName      = flag.String("service-name", "MQTT2TCPMain", "Set service name")
	flagServiceDesc      = flag.String("service-desc", "MQTT2TCP主启动进程与守护进程", "Set service description")
	flagServiceInstall   = flag.Bool("service-install", false, "Install service")
	flagServiceUninstall = flag.Bool("service-remove", false, "Remove service")
	flagServiceStart     = flag.Bool("service-start", false, "Start service")
	flagServiceStop      = flag.Bool("service-stop", false, "Stop service")
	flagChildProcess     = flag.Bool("child-process", false, "Child Process")
	processes            []*logiclib.ProcessBase
	isDaemon             bool
	runningLock          sync.Mutex
)

func init() {
	// change to current dir
	var err error
	isDaemon = true
	if appPath, err = winsvc.GetAppPath(); err != nil {
		logger.Fatal(err)
	}
	logger.Info(appPath)
	if err := os.Chdir(filepath.Dir(appPath)); err != nil {
		logger.Fatal(err)
	}
	define.InitInternalPath()
	define.CheckIsLog("daemon.log")
	//读取服务列表配置
	cfgManager := new(logiclib.ConfigFileBase)
	confs := cfgManager.LoadProcessCfg()
	if confs != nil {
		for _, conf := range confs {
			var p logiclib.ProcessBase
			p.SetFilePath(conf.Value)
			p.SetTitle(conf.Title)
			logiclib.KillIfExist(conf.Value)
			p.Init()
			processes = append(processes, &p)
		}
	}
}

//StartServer 启动服务
func StartServer() {
	runningLock.Lock()
	go logiclib.RPCServerStart(processes, &isDaemon)
	for _, p := range processes {
		p.Start()
		go p.Wait()
		//go cmdRespose(&p)
	}
	//go waitStop()
	runningLock.Lock()
	defer runningLock.Unlock()
}

func waitStop() {
	time.Sleep(time.Second * 18)
	StopServer()
}

//StopServer 停止服务
func StopServer() {
	//runningLock.Unlock()
	//runningLock.Lock()
	for _, p := range processes {
		p.SetIsDaemon(false)
		//println(p.GetTitle())
	}
	logiclib.UnLockAll("STOP")
	for _, p := range processes {
		p.Stop()
		//println(p.GetTitle())
	}
	time.Sleep(time.Second * 2)
	runningLock.Unlock()
}

func mainwin() {
	flag.Parse()
	args := flag.Args()
	for arg := range args {
		logger.Info(arg)
	}
	// install service
	if *flagServiceInstall {
		if err := winsvc.InstallService(appPath, *flagServiceName, *flagServiceDesc); err != nil {
			log.Fatalf("installService(%s, %s): %v\n", *flagServiceName, *flagServiceDesc, err)
		}
		fmt.Printf("Done\n")
		return
	}
	// remove service
	if *flagServiceUninstall {
		if err := winsvc.RemoveService(*flagServiceName); err != nil {
			log.Fatalln("removeService:", err)
		}
		fmt.Printf("Done\n")
		return
	}
	// start service
	if *flagServiceStart {
		if err := winsvc.StartService(*flagServiceName); err != nil {
			log.Fatalln("startService:", err)
		}
		fmt.Printf("Done\n")
		return
	}
	// stop service
	if *flagServiceStop {
		if err := winsvc.StopService(*flagServiceName); err != nil {
			log.Fatalln("stopService:", err)
		}
		fmt.Printf("Done\n")
		return
	}
	// run as service
	if !winsvc.InServiceMode() {
		log.Println("main:", "runService")
		if err := winsvc.RunAsService(*flagServiceName, StartServer, StopServer, false); err != nil {
			log.Fatalf("svc.Run: %v\n", err)
		}
		return
	}

	if *flagChildProcess {
		logger.Info("CHILD MODE")
		//go getCMD("EmqxServer")
	} else {
		// run as normal
		var cmdLine string
		consoleCmd := func() {
			for strings.ToUpper(cmdLine) != "EXIT" {
				fmt.Scanln(&cmdLine)
				time.Sleep(time.Second)
			}
			StopServer()
		}
		go consoleCmd()
	}

	c := make(chan os.Signal, 0)
	signal.Notify(c, syscall.SIGINT, syscall.SIGQUIT, syscall.SIGILL, syscall.SIGABRT, syscall.SIGKILL)
	var exitSignal = func() {
		s := <-c
		fmt.Println("Got signal:", s) //Got signal: terminated
		StopServer()
	}
	go exitSignal()
	StartServer()
	println("exit")
	//mainContent.Stop(false)
}
